package com.mallcloud.mall.app.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mallcloud.mall.app.config.BaseConfig;
import com.mallcloud.mall.app.service.AppProductCategoryService;
import com.mallcloud.mall.common.core.constant.CacheConstants;
import com.mallcloud.mall.common.core.constant.enums.mall.MallCommonEnum;
import com.mallcloud.mall.common.core.constant.enums.mall.ProductEnum;
import com.mallcloud.mall.product.api.entity.CategoryModel;
import com.mallcloud.mall.product.mapper.CategoryMapper;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 商品分类
 */
@Service
@AllArgsConstructor
public class AppProductCategoryServiceImpl extends ServiceImpl<CategoryMapper, CategoryModel> implements AppProductCategoryService {

	private final BaseConfig baseConfig;

	@Override
	@Cacheable(value = CacheConstants.PROJECT_CATEGORY_TREE,  unless = "#result.isEmpty()")
	public List<Tree<Long>> getMerchantCacheTree() {
		List<CategoryModel> proCategoryList = this.list(new LambdaQueryWrapper<CategoryModel>()
				.eq(CategoryModel::getStatus, MallCommonEnum.StatusEnum.Y.getCode())
		);
		List<TreeNode<Long>> collect = proCategoryList.stream()
				.filter(proCategory -> !proCategory.getCategoryId().equals(proCategory.getParentId()))
				.sorted(Comparator.comparingInt(CategoryModel::getSortOrder))
				.map(getNodeFunction())
				.collect(Collectors.toList());

		return TreeUtil.build(collect, 0L);
	}

	@Override
	@Cacheable(value = CacheConstants.PROJECT_CATEGORY_FIRST,  unless = "#result.isEmpty()")
	public List<CategoryModel> getFrontFirstCategory() {
		return this.list(new LambdaQueryWrapper<CategoryModel>()
				.eq(CategoryModel::getStatus, MallCommonEnum.StatusEnum.Y.getCode())
				.eq(CategoryModel::getCategoryLevel, ProductEnum.LevelEnum.FIRST.getLevel())
				.orderByAsc(CategoryModel::getSortOrder)
		);
}

	@Override
	@Cacheable(value = CacheConstants.PROJECT_CATEGORY_THIRD, key = "#firstId",  unless = "#result.isEmpty()")
	public List<CategoryModel> getHomeThirdCategory(Long firstId) {
		// 查询第二级 parentId=firstId(第一级分类id)
		List<Long> list = this.list(new LambdaQueryWrapper<CategoryModel>()
				.select(CategoryModel::getCategoryId)
				.eq(CategoryModel::getStatus, MallCommonEnum.StatusEnum.Y.getCode())
				.eq(CategoryModel::getParentId, firstId)
		).stream().map(CategoryModel::getCategoryId).collect(Collectors.toList());

		// 查询第三级
		return this.list(new LambdaQueryWrapper<CategoryModel>()
				.eq(CategoryModel::getStatus, MallCommonEnum.StatusEnum.Y.getCode())
				.eq(CategoryModel::getCategoryLevel, ProductEnum.LevelEnum.THIRD.getLevel())
				.in(CategoryModel::getParentId, list)
				.orderByAsc(CategoryModel::getSortOrder)
		);
	}

	@NotNull
	private Function<CategoryModel, TreeNode<Long>> getNodeFunction() {
		return proCategory -> {
			TreeNode<Long> node = new TreeNode(
					proCategory.getCategoryId(),
					proCategory.getParentId(),
					proCategory.getName(),
					proCategory.getSortOrder()
			);
			// 扩展属性
			Map<String, Object> extra = new HashMap<>();
			if (StrUtil.isNotBlank(proCategory.getIcon())) {
				// 替换成nginx静态资源地址
				extra.put("icon", String.format("%s%s", baseConfig.getNginxUrl(), StrUtil.subAfter(proCategory.getIcon(), StrUtil.SLASH, true)));
			}
			if (StrUtil.isNotBlank(proCategory.getImgUrl())) {
				// 替换成nginx静态资源地址
				extra.put("imgUrl", String.format("%s%s", baseConfig.getNginxUrl(), StrUtil.subAfter(proCategory.getImgUrl(), StrUtil.SLASH, true)));
			}
			extra.put("status", proCategory.getStatus());
			extra.put("label", proCategory.getName());
			extra.put("categoryLevel", proCategory.getCategoryLevel());
			extra.put("sortOrder", proCategory.getSortOrder());
			node.setExtra(extra);
			return node;
		};
	}
}
